

/*
* @version: 1.0
* @Author: zhanggq
* @Date: 2022-12-21 10:01:00
 * @LastEditTime: 2023-11-27 10:35:21
* @Description: 数据中心管理
*/

#ifndef   __DATACENTER_MANAGER_H__
#define   __DATACENTER_MANAGER_H__

#include <unordered_map>

#include "../../common/include/CThreadNotify.h"
#include "../../common/include/CMosquittoManager.h"
#include "../../common/include/CConfigManager.h"
#include "../../pemd/include/TaskManager.h"
#include "DcPacketManager.h"
#include "protocol_engine_config.h"

#include <pthread.h>

typedef std::unordered_map<std::string, ST_DEV_GUID>  T_DEVADDR_DEVGUID_TYPE;
typedef std::unordered_map<std::string, ST_DEV_GUID>  T_GUID_DEVGUID_TYPE;

//用于处理定值设置
typedef int (*HANDLE_SET_VALUE)(QUERY_SET_VALUE_DATAS& datas);

class  DataCenterManager
{
public:
    DataCenterManager();
    ~DataCenterManager();

    static  DataCenterManager*  getInstance();
    void    init(std::shared_ptr<CConfigManager> cm, std::shared_ptr<TaskManager> tm);
    int     connect(const char *host, int port, const char *username, const char *password, int keepalive);
    
    HANDLE_SET_VALUE c_func_handle_set_value;
    void  set_handle_func(HANDLE_SET_VALUE func);

    void    devregister_to_datacenter();
    void    modelset_to_datacenter();
    void    devunreg_from_datacenter();
    void    devregister_modelset_todc();

    //模型查询----等待订阅结束后执行
    std::list<std::string>& dc_modelname_query_waitsubscribe();

    //模型名称查询
    std::list<std::string>& dc_model_name_query();
    //模型查询
    std::list<ST_SINGLE_MODEL_INFO>& dc_model_query(const std::list<std::string>& lstModelNames);
    //模型删除
    void    dc_model_delete(const std::list<std::string>& lstModelNames);

    //数据上报
    int    dc_datareport(const std::string& strmodel, const std::string& strdev, std::list<ST_REPORT_DATAPT>& lstReportPts);
    //数据变化上报
    void   dc_datachange_report(const std::string& strmodel, const std::string& strdev, int datatype, std::list<ST_CHANGE_REPORT_DATAPT>  lstReportPts);
    //冻结数据上报
    int    dc_frozen_datareport(const std::string& strmodel, const std::string& strdev, std::list<ST_FROZEN_GROUP_DATA>& lstfrozen_group, std::string frozen_type);

    //注册关系查询
    int    dc_register_relation_query(std::list<ST_REGISTER_MODEL_INFO>& lstRegisterRelation);

    //遥控命令转发
    int    dc_transpond_remotectrl_cmd_req(std::list<ST_REMOTECTRL_CMD>& lstRemoteCtrlcmd);
    //int    dc_transpond_remotectrl_cmd_rsp(std::list<ST_REMOTECTRL_RSP>& lstRemoteCtrlRsp);

    //实时数据查询
    std::list<ST_REALTIME_QUERY_DEV_RSP>& dc_query_realtime_datas(const std::list<std::string>& lstDevs);
    int dc_query_realtime_datas(const std::list<int64_t>& devs, T_MAPPING_DATA_TYPE& mapping_datas);

    //模型对比---数据重新的查询与本地配置库的对比
    bool  model_contrast(std::list<ST_SINGLE_MODEL_INFO> lstModels);
    bool  regdev_contrast(std::list<ST_REGISTER_MODEL_INFO> lstRegisterRelation);

    static void *handle_thread(void *arg);
    static void *handle_modelname_query_thread(void *arg);

    int  set_devguid_type1(std::string& addr, ST_DEV_GUID stDevGuid);
    int  set_devguid_type2(std::string& dev, ST_DEV_GUID stDevGuid);
    std::shared_ptr<ST_DEV_GUID> get_devguid_withdev(std::string& dev);
    std::shared_ptr<ST_DEV_GUID> get_devguid_with_devid(int64_t dev_id,bool bfrozen=false);
    
    std::list<std::string> get_dc_devs();
    std::list<ST_DEV_GUID>   get_all_devguids();
    std::shared_ptr<ST_DEV_GUID> get_devguid_with_devaddr(std::string& addr);

    void print_register_relation(std::list<ST_REGISTER_MODEL_INFO>& lstRegisterRelation);
public:
    CThreadNotify  m_thread_notify;

protected:
    T_DEVADDR_DEVGUID_TYPE   c_dc_addr_devguids;
    T_GUID_DEVGUID_TYPE      c_dc_guid_devguids;

    CThreadNotify  m_thdnotify_devguid1;
    CThreadNotify  m_thdnotify_devguid2;

protected:
    int dc_dev_register(const std::list<ST_MODEL_INFO>& lstDevinfo);
    int dc_dev_unreg(const std::list<ST_UNREG_DEVINFO>& lstDevinfo);
    int get_dev_reginfo(std::list<ST_MODEL_INFO>& lstModelInfo);

    int dc_model_set(const std::string& strmodel, std::list<ST_MODEL_PTINFO>& lstModels, std::string& status);

    int save_dev_guid(std::list<ST_REGISTER_MODEL_INFO>& lstRegisterRelation);
    int subscribe_report_rsptopics(std::list<ST_REGISTER_MODEL_INFO>& lstRegisterRelation);

    void dc_model_mobusset(int64_t protocol_id,std::string model);
    void dc_model_dlt645set(int64_t protocol_id, std::string model,bool bfrozen=false);
    void dc_model_dlt698set(int64_t protocol_id, std::string model);

    void get_query_models(std::list<ST_SINGLE_MODEL_INFO>&  lstModels);
    void get_query_model_names(std::list<std::string>& lstModelNames);
    void get_register_relations(std::list<ST_REGISTER_MODEL_INFO>& lstRegisterRelation);

    void get_realtime_query_rspdata(std::list<ST_REALTIME_QUERY_DEV_RSP>& lstQueryDevs);
public:
    static DataCenterManager  m_datacenterMana;

    pthread_t       m_pthread_id;
    pthread_t       m_pthread_mn_query_id;

    int64_t         m_req_id;
    bool            m_is_receiving;
    int             m_rsp_len;
    std::string     m_status;
    bool            m_bsubscribed_end;

    DcPacketManager                             m_dpm;
    std::shared_ptr<TaskManager>                m_tm;
    std::shared_ptr<CConfigManager>             m_cm;
    std::shared_ptr<CMosquittoManager>          m_mosquitto_manager;
    
    std::list<ST_REGISTER_NOTIFYPT>             m_lstRegisterNotify;
    std::unordered_map<std::string, int64_t>    m_mpModeldesc;   //<model_id_addr,id>即<desc,id>
    std::vector<std::string>                    m_vtDevGuid;

    std::list<std::string>                      m_lstModelNames;
    std::list<ST_SINGLE_MODEL_INFO>             m_lstModels;            //模型集合
    std::list<ST_REGISTER_MODEL_INFO>           m_lstRegisterRelation;  //注册关系
    std::list<ST_REALTIME_QUERY_DEV_RSP>        m_lstRealtimeQueryRsp;  //实时数据查询(按设备)返回

    std::unordered_map<int64_t, std::unordered_map<std::string, int>>     m_mpFrozenItems;

    std::string c_msg;//用于定值处理

    void    init_mqtt();
    void    wait_recv_finished();
    void    finish_signal();
    int     subscribe_topics();
    int     handle_message(void *data, int data_len);

    std::string  get_modbus_datatype(int data_type);
    std::string  get_dlt645_datatype(int data_type,int decimmal);
    std::string  get_dlt698_datatype(int data_type);
    std::string  get_devport(std::string& channel);
    std::string  get_dc_devkey(std::string& model,std::string& port,std::string& addr,std::string& desc);
    std::string  get_comp_addr(std::string & addr, int64_t pid,bool bfrozen=false);

    void         get_dlt645_frozenitems();

    static int  datacenter_callback(CALLBACK_TYPE cb_type, void *data, int data_len, int result, void *arg);

    int get_mapping_devs(const std::list<int64_t>& devs, std::unordered_map<std::string, int64_t>& dev_guids);
    int get_modbus_point_id(MAPPING_POINT_DATA_TYPE& mapping_point);
    int get_dlt645_point_id(MAPPING_POINT_DATA_TYPE& mapping_point);
    int get_dlt698_point_id(MAPPING_POINT_DATA_TYPE& mapping_point);
    int get_point_id(MAPPING_POINT_DATA_TYPE& mapping_point);
    //
    int handle_const_value(std::string msg);
    int set_const_value(std::string msg);

};

#endif